package cn.tqfeiyang.smartadmin.commons.pagination;

import cn.tqfeiyang.smartadmin.commons.exception.BusinessException;
import cn.tqfeiyang.smartadmin.commons.toolbox.BeanUtils;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageInfo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class PageData<T> {

    /**
     * 总数
     */
    @Schema(description = "总记录数")
    private long total;

    /**
     * 当前页
     */
    @Schema(description = "当前页，默认是 1", example = "1")
    private long page;

    /**
     * 每页显示条数
     */
    @Schema(description = "每页显示记录数，默认是 15", example = "15")
    private long size;

    /**
     * 记录列表
     */
    @Schema(description = "记录列表")
    private List<T> list;

    public static <T> PageData<T> create(IPage<? extends T> resultPage) {
        PageData<T> pageData = new PageData<>();
        pageData.setTotal(resultPage.getTotal());
        pageData.setPage(resultPage.getCurrent());
        pageData.setSize(resultPage.getSize());
        pageData.setList(resultPage.getRecords().stream()
                .collect(Collectors.toList()));
        return pageData;
    }

    public static <S, R> PageData<R> create(IPage<? extends S> resultPage, Function<S, ? extends R> mapper) {
        PageData<R> pageData = new PageData<>();
        pageData.setTotal(resultPage.getTotal());
        pageData.setPage(resultPage.getCurrent());
        pageData.setSize(resultPage.getSize());
        pageData.setList(resultPage.getRecords().stream()
                .map(mapper)
                .collect(Collectors.toList()));
        return pageData;
    }

    public static <S, R> PageData<R> create(IPage<? extends S> resultPage, Class<R> destinationType) {
        return PageData.create(resultPage, item -> BeanUtils.map(item, destinationType));
    }

    /**
     * 将 PageHelper产生的 PageInfo 转换成 PageData。
     *
     * @param pageInfo PageHelper产生的 PageInfo
     * @param mapper 实体转换方法
     * @return 分页数据
     */
    public static <S, R> PageData<R> create(PageInfo<? extends S> pageInfo, Function<S, ? extends R> mapper) {
        PageData<R> pageData = new PageData<>();
        pageData.setTotal(pageInfo.getTotal());
        pageData.setPage(pageInfo.getPageNum());
        pageData.setSize(pageInfo.getSize());
        pageData.setList(pageInfo.getList().stream()
                .map(mapper)
                .collect(Collectors.toList()));
        return pageData;
    }

    /**
     * @see PageData#create(PageInfo, Function)
     */
    public static <S, R> PageData<R> create(PageInfo<? extends S> resultPage, Class<R> destinationType) {
        return PageData.create(resultPage, item -> BeanUtils.map(item, destinationType));
    }

    /**
     * 将 PageHelper产生的 List（实际上是Page类型） 转换成 PageData。
     *
     * @param list PageHelper产生的 List（实际上是Page类型）
     * @param mapper 实体转换方法
     * @return 分页数据
     */
    public static <S, R> PageData<R> create(List<? extends S> list, Function<S, ? extends R> mapper) {
        if (!(list instanceof Page)) {
            throw new BusinessException("list参数必须是Page类型");
        }
        Page<S> page = (Page<S>) list;
        PageData<R> pageData = new PageData<>();
        pageData.setTotal(page.getTotal());
        pageData.setPage(page.getPageNum());
        pageData.setSize(page.getPageSize());
        pageData.setList(page.getResult().stream()
                .map(mapper)
                .collect(Collectors.toList()));
        return pageData;
    }

    /**
     * @see PageData#create(List, Function)
     */
    public static <S, R> PageData<R> create(List<? extends S> resultPage, Class<R> destinationType) {
        return PageData.create(resultPage, item -> BeanUtils.map(item, destinationType));
    }

    /**
     * @see PageData#create(List, Function)
     */
    public static <T> PageData<T> create(List<? extends T> list) {
        if (!(list instanceof Page)) {
            throw new BusinessException("list参数必须是Page类型");
        }
        Page<T> page = (Page<T>) list;
        PageData<T> pageData = new PageData<>();
        pageData.setTotal(page.getTotal());
        pageData.setPage(page.getPageNum());
        pageData.setSize(page.getPageSize());
        pageData.setList(page.getResult().stream()
                .collect(Collectors.toList()));
        return pageData;
    }
}